package cn.bonoon.kernel.descriptors.impl;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import cn.bonoon.kernel.descriptors.ClassPropertyAccessor;

public abstract class AbstractPropertyAccessor implements ClassPropertyAccessor{
	
	private Method getterName;
	private Method setterName;
	protected final Field field;
	protected final Class<?> type;
	private final Class<?> ownerClass;

	protected AbstractPropertyAccessor(Class<?> cls, Field field) {
		this.ownerClass = cls;
		this.type = field.getType();
		this.field = field;
		String name = field.getName();
		try {
			setterName = cls.getMethod(_method("set", name), type);
		} catch (Exception e) {
			setterName = null;
			//不能对该实体进入写值
		}
		
		try{
			Method m = cls.getMethod(_method("get", name));
			if(type.equals(m.getReturnType())){
				getterName = m;
			} else {
				throw new NoSuchMethodException();
			}
		} catch(Exception e) {
			try{
				Method m = cls.getMethod(_method("is", name));
				if(type.equals(m.getReturnType())){
					getterName = m;
				}
			}catch (Exception se) {
				getterName = null;
				//不能对该实体进行取值
			}
		}
	}
	
	/**
	 * <pre>
	 * 如果是数组类型，通过该方法可以取得数组里存放的数据的类型。如：
	 * String[] array;
	 * 通过本方法可以取得String类型；
	 * 如果该属性定义的类型不是String[]类型，则返回null值
	 * </pre>
	 * @return 数组对象的类型
	 */
	public final Class<?> getComponentType(){
		return type.getComponentType();
	}
	
	public Method setter(){
		return setterName;
	}
	
	public Method getter(){
		return getterName;
	}

	public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
		return field.getAnnotation(annotationClass);
	}
	
	public <T extends Annotation> boolean isAnnotationPresent(Class<T> annotationClass){
		return field.isAnnotationPresent(annotationClass);
	}
	
	public Field getField() {
		return field;
	}

	private String _method(String pre, String name) {
		char chs[] = name.toCharArray();
		chs[0] = Character.toUpperCase(chs[0]);
		return pre + new String(chs);
	}

	/**
	 * field.getName()
	 * @return field.getName()
	 */
	public final String getName() {
		return field.getName();
	}

	public final Class<?> getType() {
		return type;
	}
	
	public final boolean sameType(ClassPropertyAccessor pa){
		return type.equals(pa.getType());
	}
	
	/**
	 * type.getName()
	 * @return type.getName()
	 */
	public final String getTypeName(){
		return type.getName();
	}

	public final boolean isEnum() {
		return type.isEnum();
	}
	
	public final boolean isPrimitive(){
		return type.isPrimitive();
	}

//	public final boolean isString() {
//		return String.class.equals(type);
//	}
	
	public final boolean isArray(){
		return type.isArray();
	}

	public Class<?> getOwnerClass() {
		return ownerClass;
	}
}